#pragma once
#include "Article.h"
#include "Inproceedings.h"

class ParseBib
{
    private:
       string sourceBibFile;
       string tidyedBibFile;
       vector <Object *> obj;
       
    private:
       void readBibFile();
       void writeBibFile();
       void printString(string);
       
    public:
       ParseBib(string _sourceBibFile, string _tidyedBibFile) {
          sourceBibFile = _sourceBibFile;
          tidyedBibFile = _tidyedBibFile;
          readBibFile();
       }
       
       void setSourceBibFile(string _sourceBibFile) {
            sourceBibFile = _sourceBibFile;
       }
       
       void setTidyedBibFile(string _tidyedBibFile) {
            tidyedBibFile = _tidyedBibFile;
       }
       
       void saveTidyedBibFile();
};

void ParseBib::readBibFile() {
    freopen(sourceBibFile.c_str(), "r", stdin);
    char line[200];
        
    while (NULL != gets(line)) {
       if (line[0]!='@') continue;
       BaseInf *baseInf;
       if (line[1] == 'a') {
          baseInf = new Article();
       } else 
       if (line[1] == 'i') {
          baseInf = new Inproceedings();
          if (line[3] == 'c') {
             baseInf->setType("incollection");
          }
       }
       string str = "";
       while (NULL != gets(line)) {
             int len = strlen(line);
             int idx = 0;
             while (' ' == line[len-1]) {
                   line[len-1] = '\0';
                   len--;
             }
             while (' ' == line[idx]) {
                   idx ++;
             }
             if (strlen(line+idx) == 1 && '}' == line[idx]) {
                break;
             }
             str += string(line+idx);
             if ('}' == line[len-2] && ',' == line[len-1]) {
                     
                if ( (str[0] == 'A' || str[0] == 'a') && str[1] == 'u' ) { //author
                   baseInf->setAuthor(str);
                } else 
                if ( str[0] == 'T' || str[0] == 't' ) { //title
                   baseInf->setTitle(str);
                } else 
                if ( baseInf->getType() == "article" && (str[0] == 'V' || str[0] == 'v') ) { //Volume
                   Article *art = static_cast<Article*>(baseInf);
                   art->setVolume(str);
                } else 
                if ( str[0] == 'P' || str[0] == 'p' ) { //pages
                   baseInf->setPages(str);
                } else 
                if ( str[0] == 'Y' || str[0] == 'y' ) { //year
                   baseInf->setYear(str);
                } else 
                if ( str[0] == 'J' || str[0] == 'j' ) { //journal
                   Article *art = static_cast<Article*>(baseInf);
                   art->setJournal(str);
                } else
                if ( baseInf->getType() == "article" && (str[0] == 'N' || str[0] == 'n') ) { //number
                   Article *art = static_cast<Article*>(baseInf);
                   art->setNumber(str);
                } else
                if ( str[0] == 'B' || str[0] == 'b' ) { //book
                   Inproceedings *inp = static_cast<Inproceedings*>(baseInf);
                   inp->setBooktitle(str);
                } 
                //printString(str);
                str = "";
             } else {
               str += string(" ");
             }             
       }
       //printf("push_back() +1\n");
       obj.push_back(baseInf);
    }
    fclose(stdin);
}

void ParseBib::printString(string str) {
     int len = str.length();
     printf("    ");
     int cnt = 0;
     for (int i = 0; i < len; i++) {
         if ( str[i] == '=' ) {
            for (int j = cnt; j < 11; j++ ) {
                printf(" ");
            }
            printf("=   ");
         } else {
           printf("%c", str[i]);
           cnt++;
         }
     }
     printf(" \n");
}

void ParseBib::writeBibFile() {
     readBibFile();
     freopen(tidyedBibFile.c_str(), "w", stdout);
     int size = obj.size();
     for (int i = 0; i < size; i++) {
         BaseInf *baseInf = static_cast<BaseInf*>(obj[i]);
         printf("@%s{ , \n", baseInf->getType().c_str());
         
         printString(baseInf->getAuthor());
         printString(baseInf->getTitle());
         
         if (baseInf->getType() == "inproceedings" || baseInf->getType() == "incollection") {
             Inproceedings *inp = static_cast<Inproceedings*>(baseInf);
             printString(inp->getBooktitle());
         }
         
         if (baseInf->getType() == "article") {
             Article *art = static_cast<Article*>(baseInf);
             printString(art->getJournal());
         }
         
         printString(baseInf->getYear());
         
         if (baseInf->getType() == "article") {
             Article *art = static_cast<Article*>(baseInf);
             printString(art->getVolume());
         }
         
         if (baseInf->getType() == "article") {
             Article *art = static_cast<Article*>(baseInf);
             printString(art->getNumber());
         }
         
         printString(baseInf->getPages());
         printf("} \n \n");
         
     }
     fclose(stdout);
}

void ParseBib::saveTidyedBibFile(){
     try {
          writeBibFile();
     }catch(exception e) {
     }
}

